using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace PseudoSmash
{
    public class Fight : Microsoft.Xna.Framework.Game
    {
        public const int FIRE = 0;
        public const int WATER = 1;
        public const int EARTH = 2;
        public const int AIR = 3;
        public const int NO_SELECT = 4;

        public const int AI_LEFT = 0;
        public const int AI_RIGHT = 1;
        public const int AI_JUMP = 2;
        public const int AI_LIGHT = 3;
        public const int AI_HEAVY = 4;
        public const int AI_SPECIAL1 = 5;
        public const int AI_SPECIAL2 = 6;
        public const int AI_SUPER = 7;
        public const int AI_GRAB = 8;
        public const int AI_SHIELD = 9;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D backgroundTexture;
        SpriteFont font;
        Player[] players;
        Platform[] platforms;
        Queue<DisjointedAttack> disjointedAttacks;
        String message = "";
        Rectangle screenRectangle;
        playerTypes pTypes;
        int winner;

        Attack[][] playerMoveSets;

        int screenWidth;
        int screenHeight;


        int[] playerSelect;
        int[] playerSelectDelay;
        int[] playerMoveSelectDelay;
        Texture2D[] selectSquares;

        int pausePlayer;
        int pauseSelect;
        int pauseDelay;
        int pauseEnterDelay;
        Texture2D[] pauseMenu;


        //Define the various states the game can be in
        public enum GameState
        {
            CharacterSelect,
            Playing,
            Paused,
            GameOver
        }
        //end enum GameState

        //Stores the current state of the game
        private GameState mCurrentState = GameState.CharacterSelect;



        public Fight()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            this.IsFixedTimeStep = true;
        }

        protected override void Initialize()
        {
            graphics.PreferredBackBufferWidth = 1600;
            graphics.PreferredBackBufferHeight = 900;
            graphics.ApplyChanges();
            players = new Player[4];
            players[0] = new Player(this, new Vector2(100, 0), 1, 0);
            players[1] = new Player(this, new Vector2(GraphicsDevice.Viewport.Width - 100, 0), 2, 0);
            players[2] = new Player(this, new Vector2(300, 0), 3, 0);
            players[3] = new Player(this, new Vector2(GraphicsDevice.Viewport.Width - 300, 0), 4, 0);
           // players[3].isAI = true;

            players[0].direction = Player.RIGHT;
            players[1].direction = Player.LEFT;
            players[2].direction = Player.RIGHT;
            players[3].direction = Player.LEFT;

            disjointedAttacks = new Queue<DisjointedAttack>();
            platforms = new Platform[2];
            platforms[0] = new Platform(this, new Vector2(-400, GraphicsDevice.Viewport.Height - 20), false, GraphicsDevice.Viewport.Width + 800);
            platforms[1] = new Platform(this, new Vector2(150, GraphicsDevice.Viewport.Height - 200), true, 180);

            Components.Add(platforms[0]);
            Components.Add(platforms[1]);


            Components.Add(players[0]);
            Components.Add(players[1]);
            Components.Add(players[2]);
            Components.Add(players[3]);

            playerSelect = new int[4];
            playerSelect[0] = NO_SELECT;
            playerSelect[1] = NO_SELECT;
            playerSelect[2] = NO_SELECT;
            playerSelect[3] = NO_SELECT;

            playerSelectDelay = new int[4];
            playerSelectDelay[0] = 0;
            playerSelectDelay[1] = 0;
            playerSelectDelay[2] = 0;
            playerSelectDelay[3] = 0;

            playerMoveSelectDelay = new int[4];
            playerMoveSelectDelay[0] = 0;
            playerMoveSelectDelay[1] = 0;
            playerMoveSelectDelay[2] = 0;
            playerMoveSelectDelay[3] = 0;

            pTypes = new playerTypes();

            playerMoveSets = new Attack[4][];


            pausePlayer = 0;
            pauseSelect = 0;
            pauseDelay = 0;
            pauseEnterDelay = 0;

            winner = 0;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("SpriteFont1");
            backgroundTexture = Content.Load<Texture2D>("MKA_SubwayArena");
            DisjointedAttack.sprite = Content.Load<Texture2D>("projectile");
            selectSquares = new Texture2D[4];
            selectSquares[0] = Content.Load<Texture2D>("select_fire");
            selectSquares[1] = Content.Load<Texture2D>("select_earth");
            selectSquares[2] = Content.Load<Texture2D>("select_water");
            selectSquares[3] = Content.Load<Texture2D>("select_air");

            pauseMenu = new Texture2D[3];
            pauseMenu[0] = Content.Load<Texture2D>("Pause_Continue");
            pauseMenu[1] = Content.Load<Texture2D>("Pause_Restart");
            pauseMenu[2] = Content.Load<Texture2D>("Pause_Quit");

            screenWidth = graphics.GraphicsDevice.PresentationParameters.BackBufferWidth;
            screenHeight = graphics.GraphicsDevice.PresentationParameters.BackBufferHeight;
            screenRectangle = new Rectangle(0, 0, screenWidth, screenHeight);
        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            switch (mCurrentState)
            {
                case GameState.Playing:

                    //Remove a player if he is dead and off the screen
                    foreach (Player play in players)
                    {
                        if (play.state == Player.NP_DEAD && (play.Position.X < 0 || play.Position.X > screenWidth))
                        {
                            Components.Remove(play);
                        }
                    }

                    /*pr
                    //////////UPDATE PROJECTILES, REMOVE THEM FROM PLAY////////
                    Queue<DisjointedAttack> newQueue = new Queue<DisjointedAttack>();
                    while (disjointedAttacks.Count != 0)
                    {
                        DisjointedAttack oj = disjointedAttacks.Dequeue();
                        proj.pos += proj.velocity;
                        if ((proj.pos.X > -400) && (proj.pos.X < screenWidth + 400))
                        {
                            newQueue.Enqueue(proj);
                        }
                    }
                    disjointedAttacks = newQueue;


                    /////PLACE NEW DISJOINTED HITBOXES INTO PLAY//////////
                    for (int i = 0; i < 4; i++)
                    {
                        if (projectileDelay[i] > 0)
                        {
                            projectileDelay[i]--;
                            if (projectileDelay[i] == 0)
                            {
                                int dirModifier = 0;
                                if (players[i].direction == -1)
                                    dirModifier = 1;
                                disjointedAttacks.Enqueue(new DisjointedAttack(new Vector2(players[i].Position.X - dirModifier * players[i].offset.X, players[i].Position.Y - players[i].offset.Y + 25), new Vector2(0, 0), i + 1,);
                            }
                        }
                    }*/

                    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                        this.Exit();

                    GamePadState g;
                    KeyboardState k = Keyboard.GetState();


                    foreach (var p in players)
                    {
                        int player = p.playerNum;
                        switch (player)
                        {
                            case 1:
                                g = GamePad.GetState(PlayerIndex.One);
                                break;
                            case 2:
                                g = GamePad.GetState(PlayerIndex.Two);
                                break;
                            case 3:
                                g = GamePad.GetState(PlayerIndex.Three);
                                break;
                            default:
                                g = GamePad.GetState(PlayerIndex.Four);
                                break;

                        }

                        if (p.state == Player.JUMP || p.state == Player.JUMP_ATTACK || p.state == Player.HIT_AIR_STUN || p.state == Player.THROWN)
                            p.Velocity -= new Vector2((float)(p.Velocity.X * .05), 0);             //air resistance
                        else
                            p.Velocity -= new Vector2((float)(p.Velocity.X * .2), 0);                //friction

                        if ((p.Position.X < -400) || (p.Position.X > screenWidth + 400))       //if they are too far off the screen, they lose
                        {
                            p.state = Player.NP_DEAD;
                        }


                        Boolean onAPlatform = false;
                        foreach (var plat in platforms)
                        {

                            if (plat.isOnPlatform(p))                                   //can't move down if on platform
                            {
                                if ((p.state == Player.JUMP) || (p.state == Player.JUMP_ATTACK) || (p.state == Player.HIT_AIR_STUN || p.state == Player.THROWN))
                                {
                                    if (p.state == Player.JUMP_ATTACK)
                                    {
                                        p.lag = playerMoveSets[p.playerNum - 1][p.attackState].landingLag;
                                        p.state = Player.LANDING;
                                        p.animCounter = 0;
                                    }
                                    else if (p.state != Player.THROWN)
                                    {
                                        p.state = Player.NEUTRAL;
                                        p.animCounter = 0;
                                    }
                                    


                                }

                                p.Position = new Vector2(p.Position.X, plat.pos.Y - p.curSpriteRect.spriteBox.Height);

                                if (p.Velocity.Y != 0)
                                    p.Velocity = new Vector2(p.Velocity.X, 0);           //lose vertical velocity when you hit the ground

                                onAPlatform = true;
                            }

                        }

                        if (!onAPlatform)
                            p.Velocity += new Vector2(0, (float).6);                         //"gravity"


                        p.Position += p.Velocity;



                        //shield exit lag
                        if (p.state == Player.SHIELD && (!g.IsButtonDown(Buttons.LeftShoulder) && !k.IsKeyDown(Keys.A)))
                        {
                            p.state = Player.NEUTRAL;
                            p.lag = 15;
                        }


                        int aiCommand = -1;
                        if (p.isAI)
                            aiCommand = AI_Decision_Maker(p);



                        //Shielding
                        if ((g.IsButtonDown(Buttons.LeftShoulder) || aiCommand == AI_SHIELD || k.IsKeyDown(Keys.A) && player == 1 || k.IsKeyDown(Keys.H) && player == 2) && p.lag == 0)
                        {
                            if (p.state == Player.NEUTRAL || p.state == Player.RUN)
                            {
                                p.state = Player.SHIELD;
                                p.animCounter = 0;
                            }

                        }
                        //Movement - Left
                        else if ((g.DPad.Left == ButtonState.Pressed || g.IsButtonDown(Buttons.LeftThumbstickLeft) || aiCommand == AI_LEFT || k.IsKeyDown(Keys.Z) && player == 1 || k.IsKeyDown(Keys.N) && player == 2) && p.lag == 0)
                        {
                            int prevDirection = p.direction;
                            if ((p.state == Player.NEUTRAL) || (p.state == Player.RUN))
                            {
                                if (p.state == Player.NEUTRAL)
                                    p.animCounter = 0;

                                p.direction = Player.LEFT;
                                p.state = Player.RUN;
                                p.Velocity = new Vector2(-6, p.Velocity.Y);

                                if (prevDirection == Player.RIGHT)                              //cause sprite to pivot around the center of the bear, not the whole sprite
                                    p.Position += new Vector2(p.curSpriteRect.hitbox.X - (p.curSpriteRect.spriteBox.Width - (p.curSpriteRect.hitbox.X + p.curSpriteRect.hitbox.Width)), 0);
                            }
                            else if (p.state == Player.JUMP)
                            {
                                p.Velocity = new Vector2(-4, p.Velocity.Y);
                                p.direction = Player.LEFT;

                                if (prevDirection == Player.RIGHT)
                                    p.Position += new Vector2(p.curSpriteRect.hitbox.X, 0);
                            }
                        }
                        //Movement-Right
                        else if ((g.DPad.Right == ButtonState.Pressed || g.IsButtonDown(Buttons.LeftThumbstickRight) || aiCommand == AI_RIGHT || k.IsKeyDown(Keys.C) && player == 1 || k.IsKeyDown(Keys.OemComma) && player == 2) && p.lag == 0)
                        {
                            int prevDirection = p.direction;
                            if ((p.state == Player.NEUTRAL) || (p.state == Player.RUN))
                            {
                                if (p.state == Player.NEUTRAL)
                                    p.animCounter = 0;

                                p.direction = Player.RIGHT;
                                p.state = Player.RUN;
                                p.Velocity = new Vector2(6, p.Velocity.Y);

                                if (prevDirection == Player.LEFT)
                                    p.Position -= new Vector2(p.curSpriteRect.hitbox.X, 0);

                            }
                            else if (p.state == Player.JUMP)
                            {
                                p.Velocity = new Vector2(4, p.Velocity.Y);
                                p.direction = Player.RIGHT;

                                if (prevDirection == Player.LEFT)
                                    p.Position -= new Vector2(p.curSpriteRect.hitbox.X, 0);
                            }


                        }
                        //They are not moving in either direction, nor shielding
                        else
                        {
                            if (p.state == Player.RUN || p.state == Player.SHIELD)
                            {
                                p.state = Player.NEUTRAL;
                                p.animCounter = 0;
                            }
                        }

                        //Movement - down. Used to fall through platforms and fast fall
                        if ((g.DPad.Down == ButtonState.Pressed || g.IsButtonDown(Buttons.LeftThumbstickDown) || k.IsKeyDown(Keys.X) && player == 1 || k.IsKeyDown(Keys.M) && player == 2) && p.lag == 0)
                        {
                            switch (p.state)
                            {
                                case Player.NEUTRAL:
                                    foreach (var plat in platforms)
                                    {
                                        if (p.Position.Y + p.curSpriteRect.spriteBox.Height == plat.pos.Y)
                                        {
                                            if (plat.canDropThrough)
                                            {
                                                p.Position += new Vector2(0, 1);
                                                p.state = Player.JUMP;
                                                p.animCounter = 3;
                                            }
                                        }
                                    }
                                    break;
                            }
                        }

                        //Up - Jump
                        if ((g.IsButtonDown(Buttons.LeftThumbstickUp) || g.IsButtonDown(Buttons.DPadUp) || aiCommand == AI_JUMP || k.IsKeyDown(Keys.S) && player == 1 || k.IsKeyDown(Keys.J) && player == 2) && p.lag == 0)
                        {
                            if (p.state == Player.RUN || p.state == Player.NEUTRAL)
                            {
                                p.animCounter = 0;
                                p.state = Player.JUMP;
                                p.Velocity += new Vector2(0, -20);
                            }

                        }
                        //Button X - Light Attack
                        if ((g.IsButtonDown(Buttons.X) || aiCommand == AI_LIGHT || k.IsKeyDown(Keys.D1) && player == 1 || k.IsKeyDown(Keys.D7) && player == 2) && p.lag == 0)
                        {
                            int prevState = p.state;
                            switch (prevState)
                            {
                                case Player.NEUTRAL:
                                case Player.RUN:
                                    p.state = Player.ATTACK;
                                    p.attackState = Player.LIGHT_ATTACK;
                                    p.animCounter = 0;
                                    break;
                                case Player.JUMP:
                                    p.state = Player.JUMP_ATTACK;
                                    p.attackState = Player.AIRLIGHT_ATTACK;
                                    p.animCounter = 0;
                                    break;
                            }
                        }
                        //Button Y - Heavy Attack
                        if ((g.IsButtonDown(Buttons.Y) || aiCommand == AI_HEAVY || k.IsKeyDown(Keys.D2) && player == 1 || k.IsKeyDown(Keys.D8) && player == 2) && p.lag == 0)
                        {
                            int prevState = p.state;
                            switch (prevState)
                            {
                                case Player.NEUTRAL:
                                case Player.RUN:
                                    p.state = Player.ATTACK;
                                    p.attackState = Player.HEAVY_ATTACK;
                                    p.animCounter = 0;
                                    break;

                                case Player.JUMP:
                                    p.state = Player.JUMP_ATTACK;
                                    p.attackState = Player.AIRHEAVY_ATTACK;
                                    p.animCounter = 0;
                                    break;
                            }
                        }
                        //Button A - Special One Attack
                        if ((g.IsButtonDown(Buttons.A) || aiCommand == AI_SPECIAL1 || k.IsKeyDown(Keys.D3) && player == 1 || k.IsKeyDown(Keys.D9) && player == 2) && p.lag == 0)
                        {
                            int prevState = p.state;
                            switch (prevState)
                            {
                                case Player.NEUTRAL:
                                case Player.RUN:
                                    p.state = Player.ATTACK;
                                    p.attackState = Player.SPECIAL_ATTACK_ONE;
                                    p.animCounter = 0;
                                    break;
                                case Player.JUMP:
                                    p.state = Player.JUMP_ATTACK;
                                    p.attackState = Player.AIRSPECIAL_ATTACK;
                                    p.animCounter = 0;
                                    if (p.playerType == WATER)
                                    {
                                        p.Velocity = new Vector2(15*p.direction, -20);
                                    }
                                    break;

                            }
                        }

                        //Button B - Special Two Attack
                        if ((g.IsButtonDown(Buttons.B) || aiCommand == AI_SPECIAL2 || k.IsKeyDown(Keys.D4) && player == 1 || k.IsKeyDown(Keys.D0) && player == 2) && p.lag == 0)
                        {
                            int prevState = p.state;
                            switch (prevState)
                            {
                                case Player.NEUTRAL:
                                case Player.RUN:
                                    p.state = Player.ATTACK;
                                    p.attackState = Player.SPECIAL_ATTACK_TWO;
                                    p.animCounter = 0;
                                    break;
                            }
                        }

                        //RightBumper - Super Attack
                        if ((g.IsButtonDown(Buttons.RightShoulder) || aiCommand == AI_SUPER || k.IsKeyDown(Keys.D5) && player == 1 || k.IsKeyDown(Keys.OemMinus) && player == 2) && p.lag == 0)
                        {
                            if (p.superCounter >= 100)
                            {
                                int prevState = p.state;
                                switch (prevState)
                                {
                                    case Player.NEUTRAL:
                                    case Player.RUN:
                                        p.state = Player.ATTACK;
                                        p.attackState = Player.SUPER_ATTACK;
                                        p.animCounter = 0;
                                        p.superCounter = 0;
                                        break;

                                }
                            }
                        }

                        //Right Trigger - Grab
                        if ((g.IsButtonDown(Buttons.RightTrigger) || aiCommand == AI_GRAB || k.IsKeyDown(Keys.D6)) && p.lag == 0)
                        {
                            int prevState = p.state;
                            switch (prevState)
                            {
                                case Player.NEUTRAL:
                                case Player.RUN:
                                    p.state = Player.ATTACK;
                                    p.attackState = Player.GRAB;
                                    p.animCounter = 0;
                                    break;
                            }

                        }

                        //Bug Mode
                        if (k.IsKeyDown(Keys.B) && p.playerNum == 1 && p.bugTimer == 0)
                        {
                            p.bugTimer = 20;
                            foreach (var ply in players)
                            {
                                if (ply.bugMode == true)
                                {
                                    ply.bugMode = false;
                                }
                                else
                                {
                                    ply.bugMode = true;
                                }
                            }
                        }

                        if (pauseEnterDelay > 0)
                            pauseEnterDelay--;

                        //Pause the game
                        if ((g.IsButtonDown(Buttons.Start) || k.IsKeyDown(Keys.Enter)) && pauseEnterDelay == 0)
                        {
                            mCurrentState = GameState.Paused;
                            pausePlayer = p.playerNum;
                            pauseEnterDelay = 60;

                            foreach (Platform plat in platforms)
                            {
                                plat.gameOn = false;
                            }
                            foreach (Player pla in players)
                            {
                                pla.gameOn = false;
                            }
                        }

                        ////////Collision Detection - Players (if you are currently hitting other players)///////////////////

                        foreach (var otherPlayer in players)
                        {
                            if (otherPlayer != p)   //can't hit yourself
                            {

                                p.trueAttackHitbox = calculateTAH(p, p.curSpriteRect);
                                Rectangle intersect = Rectangle.Intersect(
                                    p.trueAttackHitbox,
                                    otherPlayer.trueHitBox);
                                if (intersect.X != 0 && p.attackState != Player.THROW) //if the x intersects, and the attack is not a throw (to prevent throwing multiple people)
                                {
                                    if ((otherPlayer.hitInvulnCounter[p.playerNum - 1] == 0) || (otherPlayer.hitInvulnMove[p.playerNum - 1] != p.attackState))
                                    {

                                        if (otherPlayer.state != Player.SHIELD || p.attackState == Player.GRAB)
                                            p.superCounter += playerMoveSets[p.playerNum - 1][p.attackState].superPower;

                                        if (p.attackState == Player.GRAB)
                                        {
                                            p.attackState = Player.THROW;
                                            p.animCounter = 0;
                                            otherPlayer.state = Player.THROWN;
                                            otherPlayer.thrownDirection = p.direction;
                                            otherPlayer.animCounter = 0;
                                            otherPlayer.curSpriteRect = otherPlayer.hitstunned;
                                        }
                                    }
                                    otherPlayer.attacked(playerMoveSets[p.playerNum - 1][p.attackState], p.direction, p.playerNum);
                                }

                            }
                        }

                        /*///////Collision Detection - Disjointed Hitboxes (if you are currently being hit by a projectile)///////////////////
                        Queue<DisjointedAttack> newQueue2 = new Queue<DisjointedAttack>();
                        while (disjointedAttacks.Count != 0)
                        {
                            DisjointedAttack proj = disjointedAttacks.Dequeue();
                            if (proj.player != player)
                            {
                                Rectangle curProjRect = new Rectangle((int)proj.pos.X, (int)proj.pos.Y, DisjointedAttack.sprite.Width, DisjointedAttack.sprite.Height);
                                if (curProjRect.Intersects(p.curSpriteRect.hitbox))
                                {/*
                                    p.attacked(playerMoveSets[proj.player - 1][Player.SPECIAL_ATTACK], (int)(proj.velocity.X / Math.Abs(proj.velocity.X)), proj.player);
                                    players[proj.player - 1].superCounter += playerMoveSets[proj.player - 1][Player.SPECIAL_ATTACK].superPower;
                                }
                                else
                                    newQueue2.Enqueue(proj);
                            }
                            else
                            {
                                newQueue2.Enqueue(proj);
                            }
                        }
                        disjointedAttacks = newQueue2;

                        */

                    }

                    //check for a winner
                    int numPlayersRemaining = 0;
                    foreach (Player pl in players)
                    {
                        if (pl.state != Player.NP_DEAD)
                        {
                            numPlayersRemaining++;
                            winner = pl.playerNum;
                        }
                    }

                    if (numPlayersRemaining == 1)
                        mCurrentState = GameState.GameOver;
                    else if (numPlayersRemaining == 0)
                    {
                        winner = 5;
                        mCurrentState = GameState.GameOver;
                    }
                    else
                        winner = 0;

                    //end checking for a winner

                    break;
                case GameState.CharacterSelect:
                    GamePadState g2;
                    KeyboardState k2 = Keyboard.GetState();

                    for (int i = 0; i < 4; i++)
                    {
                        switch (i)
                        {
                            case 1:
                                g2 = GamePad.GetState(PlayerIndex.One);
                                break;
                            case 2:
                                g2 = GamePad.GetState(PlayerIndex.Two);
                                break;
                            case 3:
                                g2 = GamePad.GetState(PlayerIndex.Three);
                                break;
                            default:
                                g2 = GamePad.GetState(PlayerIndex.Four);
                                break;

                        }

                        if (playerSelectDelay[i] > 0)
                            playerSelectDelay[i]--;

                        if (playerMoveSelectDelay[i] > 0)
                            playerMoveSelectDelay[i]--;

                        if ((g2.IsButtonDown(Buttons.Start) || k2.IsKeyDown(Keys.Space)) && playerSelectDelay[i] == 0)
                        {
                            if (playerSelect[i] == NO_SELECT)  //if the player is not in yet
                            {
                                playerSelect[i] = FIRE;
                                playerSelectDelay[i] = 15;
                            }
                            else                               //otherwise, start the game
                            {
                                foreach (var plat in platforms)
                                {
                                    plat.gameOn = true;
                                }
                                foreach (var ply in players)
                                {
                                    ply.gameOn = true;
                                    if (ply.playerNum == 1)     //get rid of this if statement for deployment on xbox
                                        ply.playerType = playerSelect[ply.playerNum - 1];
                                        
                                    ply.loadRectangles();
                                    playerMoveSets[ply.playerNum - 1] = pTypes.getAttackSet(ply.playerType);
                                }
                                mCurrentState = GameState.Playing;
                            }
                        }

                        //control selection left and right
                        if ((g2.IsButtonDown(Buttons.LeftThumbstickLeft) || k2.IsKeyDown(Keys.Left)) && playerMoveSelectDelay[i] == 0 && playerSelect[i] != 0)
                        {
                            playerSelect[i]--;
                            playerMoveSelectDelay[i] = 15;
                        }

                        if ((g2.IsButtonDown(Buttons.LeftThumbstickRight) || k2.IsKeyDown(Keys.Right)) && playerMoveSelectDelay[i] == 0 && playerSelect[i] != 3)
                        {
                            playerSelect[i]++;
                            playerMoveSelectDelay[i] = 15;
                        }
                    }
                    break;
                case GameState.Paused:
                    GamePadState g3;
                    KeyboardState k3 = Keyboard.GetState();

                    //only the player who paused can control the pause menu
                    switch (pausePlayer)
                    {
                        case 1:
                            g3 = GamePad.GetState(PlayerIndex.One);
                            break;
                        case 2:
                            g3 = GamePad.GetState(PlayerIndex.Two);
                            break;
                        case 3:
                            g3 = GamePad.GetState(PlayerIndex.Three);
                            break;
                        default:
                            g3 = GamePad.GetState(PlayerIndex.Four);
                            break;

                    }

                    if (pauseDelay > 0)
                        pauseDelay--;


                    //control selection left and right
                    if ((g3.IsButtonDown(Buttons.LeftThumbstickUp) || k3.IsKeyDown(Keys.Up)) && pauseDelay == 0 && pauseSelect != 0)
                    {
                        pauseSelect--;
                        pauseDelay = 15;
                    }

                    if ((g3.IsButtonDown(Buttons.LeftThumbstickDown) || k3.IsKeyDown(Keys.Down)) && pauseDelay == 0 && pauseSelect != 2)
                    {
                        pauseSelect++;
                        pauseDelay = 15;
                    }

                    if (pauseEnterDelay > 0)
                        pauseEnterDelay--;


                    if ((g3.IsButtonDown(Buttons.Start) || k3.IsKeyDown(Keys.Enter)) && pauseEnterDelay == 0)
                    {
                        pauseEnterDelay = 60;

                        switch (pauseSelect)
                        {
                            case 0:
                                mCurrentState = GameState.Playing;
                                foreach (Platform plat in platforms)
                                {
                                    plat.gameOn = true;
                                }
                                foreach (Player player in players)
                                {
                                    player.gameOn = true;
                                }
                                break;
                            case 1:
                                mCurrentState = GameState.CharacterSelect;
                                foreach (Platform plat in platforms)
                                {
                                    plat.gameOn = false;
                                }
                                foreach (Player player in players)
                                {
                                    if (Components.Contains(player))
                                        Components.Remove(player);
                                }
                                Initialize();
                                break;

                            case 2:
                                Exit();
                                break;
                        }
                    }

                    break;

            }




            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            spriteBatch.Begin();

            switch (mCurrentState)
            {
                case GameState.CharacterSelect:
                    /*
                    spriteBatch.Draw(backgroundTexture, screenRectangle, Color.White);
                    Vector2 txtPos = new Vector2(30, screenHeight - 50);
                    spriteBatch.DrawString(font, "Press 'Space' to start the fight!", txtPos, Color.White, 0, new Vector2(0, 0), .25f, SpriteEffects.None, 0);
                    spriteBatch.DrawString(font, "Use your attacks to increase your opponents pain level.", txtPos + new Vector2(0, -75), Color.YellowGreen, 0, new Vector2(0, 0), .25f, SpriteEffects.None, 0);
                    spriteBatch.DrawString(font, "When they are at 100 pain, use a strong attack to finish them off.", txtPos + new Vector2(0, -50), Color.YellowGreen, 0, new Vector2(0, 0), .25f, SpriteEffects.None, 0);
                    spriteBatch.DrawString(font, "If you reach 70 pain, you'll be able to use a super move one time.", txtPos + new Vector2(0, -25), Color.YellowGreen, 0, new Vector2(0, 0), .25f, SpriteEffects.None, 0);
                    spriteBatch.DrawString(font, "Work in Progress Multiplayer Platformer", txtPos + new Vector2(75, -300), Color.SteelBlue, 0, new Vector2(0, 0), .5f, SpriteEffects.None, 0);
                    spriteBatch.DrawString(font, "Fighter Title in Space", txtPos + new Vector2(75, -250), Color.SteelBlue, 0, new Vector2(0, 0), .5f, SpriteEffects.None, 0);
                    */

                    Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);

                    //backgrounds
                    Color[] backgrounds = new Color[5];
                    backgrounds[0] = Color.Red;
                    backgrounds[1] = Color.DarkBlue;
                    backgrounds[2] = Color.Brown;
                    backgrounds[3] = Color.Gray;
                    backgrounds[4] = Color.White;

                    spriteBatch.Draw(pixel, new Rectangle(0, 0, screenWidth / 2, screenHeight / 2), backgrounds[playerSelect[0]]);
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth / 2, 0, screenWidth / 2, screenHeight / 2), backgrounds[playerSelect[1]]);
                    spriteBatch.Draw(pixel, new Rectangle(0, screenHeight / 2, screenWidth / 2, screenHeight / 2), backgrounds[playerSelect[2]]);
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth / 2, screenHeight / 2, screenWidth / 2, screenHeight / 2), backgrounds[playerSelect[3]]);


                    //lines
                    pixel.SetData(new[] { Color.White });
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth / 2 - 2, 0, 4, screenHeight), Color.Black);
                    spriteBatch.Draw(pixel, new Rectangle(0, screenHeight / 2 - 2, screenWidth, 4), Color.Black);

                    //if the player is not in yet
                    String playPrompt = "Press Start to Play!";
                    Vector2 pOrigin = font.MeasureString(playPrompt) / 2;

                    if (playerSelect[0] == NO_SELECT)
                        spriteBatch.DrawString(font, playPrompt, new Vector2(screenWidth / 4, screenHeight / 4), Color.Red, 0, pOrigin, .3f, SpriteEffects.None, .5f);
                    if (playerSelect[1] == NO_SELECT)
                        spriteBatch.DrawString(font, playPrompt, new Vector2(screenWidth * 3 / 4, screenHeight / 4), Color.Red, 0, pOrigin, .3f, SpriteEffects.None, .5f);
                    if (playerSelect[2] == NO_SELECT)
                        spriteBatch.DrawString(font, playPrompt, new Vector2(screenWidth / 4, screenHeight * 3 / 4), Color.Red, 0, pOrigin, .3f, SpriteEffects.None, .5f);
                    if (playerSelect[3] == NO_SELECT)
                        spriteBatch.DrawString(font, playPrompt, new Vector2(screenWidth * 3 / 4, screenHeight * 3 / 4), Color.Red, 0, pOrigin, .3f, SpriteEffects.None, .5f);

                    //if the player is selecting his/her class

                    if (playerSelect[0] != NO_SELECT)
                    {
                        spriteBatch.Draw(selectSquares[playerSelect[0]], new Rectangle(screenWidth / 4 - 145, screenHeight / 4 - 40, 290, 80), Color.White);
                    }
                    if (playerSelect[1] != NO_SELECT)
                    {
                        spriteBatch.Draw(selectSquares[playerSelect[1]], new Rectangle(screenWidth * 3 / 4 - 145, screenHeight / 4 - 40, 290, 80), Color.White);
                    }
                    if (playerSelect[2] != NO_SELECT)
                    {
                        spriteBatch.Draw(selectSquares[playerSelect[2]], new Rectangle(screenWidth / 4 - 145, screenHeight * 3 / 4 - 40, 290, 80), Color.White);
                    }
                    if (playerSelect[3] != NO_SELECT)
                    {
                        spriteBatch.Draw(selectSquares[playerSelect[3]], new Rectangle(screenWidth * 3 / 4 - 145, screenHeight * 3 / 4 - 30, 290, 80), Color.White);
                    }


                    break;


                case GameState.Playing:
                    spriteBatch.Draw(backgroundTexture, screenRectangle, Color.White);
                    drawScores(spriteBatch);

                    //directions
                    String directionsOne = "Move: z,x,c,s \nAttacks:1,2,3,4 \nShield:a \nBugmode:b";
                    String directionsTwo = "Move: n,m,comma,J \nAttacks:7,8,9,0 \nShield:H";
                    Vector2 d1Origin = font.MeasureString(directionsOne) / 2;
                    Vector2 d2Origin = font.MeasureString(directionsTwo) / 2;
                    Vector2 d1Pos = new Vector2(80, 40);
                    Vector2 d2Pos = new Vector2(screenWidth - 80, 30);
                    spriteBatch.DrawString(font, directionsOne, d1Pos, Color.Red, 0, d1Origin, .3f, SpriteEffects.None, .5f);
                    spriteBatch.DrawString(font, directionsTwo, d2Pos, Color.Red, 0, d2Origin, .3f, SpriteEffects.None, .5f);

                    foreach (var proj in disjointedAttacks)
                    {
                        if (proj.velocity.X > 0)
                            spriteBatch.Draw(DisjointedAttack.sprite, proj.pos, null, Color.White, 0, new Vector2(0, 0), new Vector2(1, 1), SpriteEffects.None, 0);
                        else
                            spriteBatch.Draw(DisjointedAttack.sprite, proj.pos, null, Color.White, 0, new Vector2(0, 0), new Vector2(1, 1), SpriteEffects.FlipHorizontally, 0);
                    }
                    break;

                case GameState.GameOver:
                    drawScores(spriteBatch);

                    //winner message
                    if (winner == 0)
                        message = "Draw!";
                    else
                    {
                        message = "Player ";
                        if (winner == 1)
                            message += "One ";
                        else if (winner == 2)
                            message += "Two ";
                        else if (winner == 3)
                            message += "Three ";
                        else if (winner == 4)
                            message += "Four";
                        message += "Wins!";
                    }

                    Vector2 messageOrigin = font.MeasureString(message) / 2;
                    Vector2 messagePos = new Vector2(screenWidth / 2, screenHeight / 2);
                    spriteBatch.DrawString(font, message, messagePos, Color.Red, 0, messageOrigin, 1.0f, SpriteEffects.None, .5f);

                    break;

                case GameState.Paused:
                    spriteBatch.Draw(pauseMenu[pauseSelect], new Rectangle(screenWidth / 2 - 275, screenHeight / 2 - 125, 550, 250), Color.White);
                    break;
            }
            spriteBatch.End();

            base.Draw(gameTime);
        }

        public void drawScores(SpriteBatch spriteBatch)
        {

            Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
            pixel.SetData(new[] { Color.White });


            if (players[0].state != Player.NP_DEAD)
            {
                String scoreOne = (players[0].pain).ToString();
                Vector2 s1Origin = font.MeasureString(scoreOne) / 2;
                Vector2 s1Pos = new Vector2(100, screenHeight - 50);
                spriteBatch.DrawString(font, scoreOne, s1Pos, Color.Red, 0, s1Origin, 1.0f, SpriteEffects.None, .5f);

                if (players[0].superCounter < 100)
                    spriteBatch.Draw(pixel, new Rectangle(50, screenHeight - 25, players[0].superCounter, 20), Color.ForestGreen);
                else
                    spriteBatch.Draw(pixel, new Rectangle(50, screenHeight - 25, 100, 20), Color.Yellow);

            }

            if (players[1].state != Player.NP_DEAD)
            {
                String scoreTwo = (players[1].pain).ToString();
                Vector2 s2Origin = font.MeasureString(scoreTwo) / 2;
                Vector2 s2Pos = new Vector2(screenWidth - 100, screenHeight - 50);
                spriteBatch.DrawString(font, scoreTwo, s2Pos, Color.Red, 0, s2Origin, 1.0f, SpriteEffects.None, .5f);

                if (players[1].superCounter < 100)
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth - 150, screenHeight - 25, players[1].superCounter, 20), Color.ForestGreen);
                else
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth - 150, screenHeight - 25, 100, 20), Color.Yellow);
            }

            if (players[2].state != Player.NP_DEAD)
            {
                String scoreThree = (players[2].pain).ToString();
                Vector2 s3Origin = font.MeasureString(scoreThree) / 2;
                Vector2 s3Pos = new Vector2(300, screenHeight - 50);
                spriteBatch.DrawString(font, scoreThree, s3Pos, Color.Red, 0, s3Origin, 1.0f, SpriteEffects.None, .5f);

                if (players[2].superCounter < 100)
                    spriteBatch.Draw(pixel, new Rectangle(250, screenHeight - 25, players[2].superCounter, 20), Color.ForestGreen);
                else
                    spriteBatch.Draw(pixel, new Rectangle(250, screenHeight - 25, 100, 20), Color.Yellow);
            }

            if (players[3].state != Player.NP_DEAD)
            {
                String scoreFour = (players[3].pain).ToString();
                Vector2 s4Origin = font.MeasureString(scoreFour) / 2;
                Vector2 s4Pos = new Vector2(screenWidth - 300, screenHeight - 50);
                spriteBatch.DrawString(font, scoreFour, s4Pos, Color.Red, 0, s4Origin, 1.0f, SpriteEffects.None, .5f);

                if (players[3].superCounter < 100)
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth - 350, screenHeight - 25, players[3].superCounter, 20), Color.ForestGreen);
                else
                    spriteBatch.Draw(pixel, new Rectangle(screenWidth - 350, screenHeight - 25, 100, 20), Color.Yellow);
            }



        }

        private int AI_Decision_Maker(Player p)
        {

            ////////if the player is an A.I., act accordingly (assumes 1v1, playing against player 1/////////
            int aiCommand = -1;
            int choice = 0;
            Random r = new Random();
            int random;
            Player opp = players[0];
            switch (opp.state)
            {
                case Player.NEUTRAL:
                    if (p.state == Player.JUMP || p.state == Player.JUMP_ATTACK || p.state == Player.HIT_AIR_STUN) //if the ai is in the air
                    {
                        random = r.Next(100);
                        if ((p.Position.X > (opp.Position - opp.offset).X && p.Position.X < (opp.Position + opp.offset).X) && (random == 0)) //if over the opponent, small chance to AS
                            aiCommand = AI_SPECIAL1;

                        spriteFrame futureSpriteFrame = p.attackLoop[Player.AIRHEAVY_ATTACK][p.attackLoop[Player.AIRHEAVY_ATTACK].Length / 2]; //the middle spriteRect of the correct attack
                        Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        trueAttackHitBox.Y += 200; //the ai must be above the opponent so that the knee has time to come out
                        trueAttackHitBox.X += 36 * p.direction;
                        if (trueAttackHitBox.Intersects(opp.trueHitBox)) //small chance the ai will knee the opponent if it can 
                        {
                            aiCommand = AI_HEAVY;
                        }

                        else //otherwise, move towards the opponent
                        {
                            if (opp.Position.X < p.Position.X)
                                aiCommand = AI_LEFT;
                            else
                                aiCommand = AI_RIGHT;
                        }
                    }
                    else
                    {
                        if (p.superCounter == 100) //if the other player is in neutral, AI should super if it can 
                            aiCommand = AI_SUPER;
                        else
                        {
                            random = r.Next(100);

                            //4 choices = 4 attacks it could try to do
                            if (random < 90)
                                choice = 0;
                            else if (random < 95)
                                choice = 1;
                            else if (random < 99)
                                choice = 2;
                            else
                                choice = 3;

                            int[] choiceMeaning = { Player.LIGHT_ATTACK, Player.HEAVY_ATTACK, Player.SPECIAL_ATTACK_ONE, Player.SPECIAL_ATTACK_TWO };
                            int[] choiceAI = { AI_LIGHT, AI_HEAVY, AI_SPECIAL1, AI_SPECIAL2 };

                            spriteFrame futureSpriteFrame = p.attackLoop[choiceMeaning[choice]][p.attackLoop[choiceMeaning[choice]].Length / 2]; //the middle spriteRect of the correct attack
                            Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);

                            if (trueAttackHitBox.Intersects(opp.trueHitBox)) //if the randomly chosen attack would hit the target, do it
                            {
                                aiCommand = choiceAI[choice];
                            }
                            else //otherwise
                            {
                                random = r.Next(100);
                                float dir = p.Position.X - opp.Position.X;
                                if (random < 98) //run closer
                                {
                                    if (dir < 0) //opponent is to the right of you 
                                        aiCommand = AI_RIGHT;
                                    else //opponent is to the left of you
                                        aiCommand = AI_LEFT;
                                }
                                else if (random < 99) //jump closer
                                {
                                    aiCommand = AI_JUMP;
                                }
                                else // s1
                                {
                                    aiCommand = AI_SPECIAL1;
                                }


                            }
                        }


                    }


                    break;
                case Player.RUN:
                    if (p.state == Player.JUMP || p.state == Player.JUMP_ATTACK || p.state == Player.HIT_AIR_STUN) //if the ai is in the air
                    {
                        random = r.Next(100);
                        if ((p.Position.X > (opp.Position - opp.offset).X && p.Position.X < (opp.Position + opp.offset).X) && (random == 0)) //if over the opponent, small chance to AS
                            aiCommand = AI_SPECIAL1;

                        spriteFrame futureSpriteFrame = p.attackLoop[Player.AIRHEAVY_ATTACK][p.attackLoop[Player.AIRHEAVY_ATTACK].Length / 2]; //the middle spriteRect of the correct attack
                        Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        trueAttackHitBox.Y += 200; //the ai must be above the opponent so that the knee has time to come out
                        trueAttackHitBox.X += 36 * p.direction;
                        if (trueAttackHitBox.Intersects(opp.trueHitBox)) //the ai will knee the opponent if it can 
                        {
                            aiCommand = AI_HEAVY;
                        }
                        else //otherwise, move towards the opponent
                        {
                            if (opp.Position.X < p.Position.X)
                                aiCommand = AI_LEFT;
                            else
                                aiCommand = AI_RIGHT;
                        }
                    }
                    else
                    {
                        if (p.superCounter == 100) //AI should super if it can 
                            aiCommand = AI_SUPER;
                        else
                        {
                            random = r.Next(100);

                            //4 choices = 4 attacks it could try to do
                            if (random < 25)
                                choice = 0;
                            else if (random < 50)
                                choice = 1;
                            else if (random < 60)
                                choice = 2;
                            else
                                choice = 3;

                            int[] choiceMeaning = { Player.LIGHT_ATTACK, Player.HEAVY_ATTACK, Player.SPECIAL_ATTACK_ONE, Player.SPECIAL_ATTACK_TWO };
                            int[] choiceAI = { AI_LIGHT, AI_HEAVY, AI_SPECIAL1, AI_SPECIAL2 };

                            spriteFrame futureSpriteFrame = p.attackLoop[choiceMeaning[choice]][p.attackLoop[choiceMeaning[choice]].Length / 2]; //the middle spriteRect of the correct attack
                            Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);

                            if (trueAttackHitBox.Intersects(opp.trueHitBox)) //if the randomly chosen attack would hit the target, do it
                            {
                                aiCommand = choiceAI[choice];
                            }
                            else //otherwise
                            {
                                random = r.Next(100);
                                float dir = p.Position.X - opp.Position.X;
                                if (random < 98) //run closer
                                {
                                    if (dir < 0) //opponent is to the right of you 
                                        aiCommand = AI_RIGHT;
                                    else //opponent is to the left of you
                                        aiCommand = AI_LEFT;
                                }
                                else //jump closer
                                {
                                    aiCommand = AI_JUMP;
                                }



                            }
                        }


                    }


                    break;

                case Player.JUMP:
                case Player.HIT_AIR_STUN:
                    if (p.state != Player.JUMP)
                        aiCommand = AI_JUMP;
                    else
                    {
                        //use an appropriate air move, if it will hit

                        spriteFrame futureSpriteFrame = p.attackLoop[Player.AIRHEAVY_ATTACK][p.attackLoop[Player.AIRHEAVY_ATTACK].Length / 2];
                        Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        trueAttackHitBox.Y += 200 + (int)opp.Velocity.Y * 6; //guess the timing of the knee
                        trueAttackHitBox.X += 36 * p.direction;
                        if (trueAttackHitBox.Intersects(opp.trueHitBox))
                        {
                            aiCommand = AI_HEAVY;
                        }

                        futureSpriteFrame = p.attackLoop[Player.AIRSPECIAL_ATTACK][p.attackLoop[Player.AIRSPECIAL_ATTACK].Length / 2];
                        trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        if (trueAttackHitBox.Intersects(opp.trueHitBox))
                        {
                            aiCommand = AI_SPECIAL1;
                        }

                        futureSpriteFrame = p.attackLoop[Player.AIRLIGHT_ATTACK][p.attackLoop[Player.AIRLIGHT_ATTACK].Length / 2];
                        trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        if (trueAttackHitBox.Intersects(opp.trueHitBox))
                        {
                            aiCommand = AI_LIGHT;
                        }

                        if (aiCommand == -1)
                        { //not in range of any of those attacks, move towards oponent
                            float dir = p.Position.X - opp.Position.X;
                            if (dir < 0) //opponent is to the right of you 
                                aiCommand = AI_RIGHT;
                            else //opponent is to the left of you
                                aiCommand = AI_LEFT;
                        }


                    }
                    break;

                case Player.ATTACK:
                case Player.JUMP_ATTACK:
                    aiCommand = AI_SHIELD;
                    /*
                    spriteFrame enemyFutureSpriteFrame = opp.attackLoop[opp.attackState][opp.attackLoop[opp.attackState].Length / 2];
                    Rectangle enemyTrueAttackHitBox = calculateTAH(p, enemyFutureSpriteFrame);
                    if (opp.state == Player.JUMP_ATTACK)
                        enemyTrueAttackHitBox.X += opp.attackLoop[opp.attackState].Length / 2 * 3 * 6 * opp.direction; //move their hitbox to how far they could move before the attack was halfway done

                    Rectangle myMovingHitbox = p.trueHitBox;
                    myMovingHitbox.X += opp.attackLoop[opp.attackState].Length / 2 * 3 * 6 * opp.direction; //move my hitbox to how far I could run before this attack was halfway done
                    if (enemyTrueAttackHitBox.Intersects(p.trueHitBox)) //if the enemy could hit me, shield
                        aiCommand = AI_SHIELD;
                    else //run away
                    {
                        float dir = p.Position.X - opp.Position.X;
                        if (dir < 0) //opponent is to the right of you 
                            aiCommand = AI_LEFT;
                        else //opponent is to the left of you
                            aiCommand = AI_RIGHT;
                    }
                    */
                    break;

                case Player.SHIELD:
                    if (p.state != Player.JUMP)
                    {
                        spriteFrame futureSpriteFrame = p.attackLoop[Player.GRAB][2]; //the middle spriteRect of the correct attack
                        Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);
                        if (trueAttackHitBox.Intersects(opp.trueHitBox)) //the ai will grab the opponent if it can 
                        {
                            aiCommand = AI_GRAB;
                        }
                        else
                        {
                            float dir = p.Position.X - opp.Position.X;
                            if (dir < 0) //opponent is to the right of you 
                                aiCommand = AI_RIGHT;
                            else //opponent is to the left of you
                                aiCommand = AI_LEFT;
                        }
                    }
                    else //move towards opponent
                    {
                        float dir = p.Position.X - opp.Position.X;
                        if (dir < 0) //opponent is to the right of you 
                            aiCommand = AI_RIGHT;
                        else //opponent is to the left of you
                            aiCommand = AI_LEFT;

                    }
                    break;

                case Player.HIT_STUN:
                case Player.LANDING:
                case Player.THROWN:
                    if (p.state == Player.JUMP || p.state == Player.JUMP_ATTACK || p.state == Player.HIT_AIR_STUN) //if the ai is in the air, close the gap
                    {
                        if (opp.Position.X < p.Position.X)
                            aiCommand = AI_LEFT;
                        else
                            aiCommand = AI_RIGHT;
                    }
                    else
                    {

                        random = r.Next(100);

                        //4 choices = 4 attacks it could try to do
                        if (random < 65)
                            choice = 0;
                        else if (random < 85)
                            choice = 1;
                        else if (random < 95)
                            choice = 2;
                        else
                            choice = 3;

                        int[] choiceMeaning = { Player.HEAVY_ATTACK, Player.SPECIAL_ATTACK_ONE, Player.SPECIAL_ATTACK_TWO, Player.LIGHT_ATTACK };
                        int[] choiceAI = { AI_HEAVY, AI_SPECIAL1, AI_SPECIAL2, AI_LIGHT };

                        spriteFrame futureSpriteFrame = p.attackLoop[choiceMeaning[choice]][p.attackLoop[choiceMeaning[choice]].Length / 2]; //the middle spriteRect of the correct attack
                        Rectangle trueAttackHitBox = calculateTAH(p, futureSpriteFrame);

                        if (trueAttackHitBox.Intersects(opp.trueHitBox)) //if the randomly chosen attack would hit the target, do it
                        {
                            aiCommand = choiceAI[choice];
                        }
                        else //otherwise run closer
                        {
                            float dir = p.Position.X - opp.Position.X;
                            if (dir < 0) //opponent is to the right of you 
                                aiCommand = AI_RIGHT;
                            else //opponent is to the left of you
                                aiCommand = AI_LEFT;



                        }



                    }



                    break;





            }

            return aiCommand;


        }

        //calculates the true attack hitbox for a player given a sprite
        public Rectangle calculateTAH(Player attacker, spriteFrame attackerSprite)
        {

            //collision detect - find true locations of hitboxes
            Rectangle tempAttackHitbox;
            Vector2 pos = (attacker.Position - attacker.offset);
            if (attacker.direction == Player.RIGHT) // facing right
            {

                tempAttackHitbox = new Rectangle(attackerSprite.attackHitBox.X + (int)pos.X, attackerSprite.attackHitBox.Y + (int)pos.Y,
                                           attackerSprite.attackHitBox.Width, attackerSprite.attackHitBox.Height);
            }
            else // facing left
            {
                tempAttackHitbox = new Rectangle((int)pos.X + attackerSprite.spriteBox.Width - attackerSprite.attackHitBox.X - attackerSprite.attackHitBox.Width,
                                             (int)pos.Y + attackerSprite.attackHitBox.Y,
                                             attackerSprite.attackHitBox.Width, attackerSprite.attackHitBox.Height);
            }

            return tempAttackHitbox;
        }



    }

    //Represents any platform/floor in the environment
    class Platform : DrawableGameComponent
    {
        public Vector2 pos;
        public float length;
        public Boolean canDropThrough;
        public SpriteBatch spriteBatch;
        public Texture2D spriteSheet;
        public Texture2D spriteSheet2;
        public Boolean gameOn;

        public Platform(Game g, Vector2 startPos, Boolean droppable, float l)
            : base(g)
        {
            canDropThrough = droppable;
            pos = startPos;
            length = l;
            gameOn = false;
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            spriteSheet = Game.Content.Load<Texture2D>("bigplat");
            spriteSheet2 = Game.Content.Load<Texture2D>("smallplat");
            base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            if (gameOn == true)
            {
                spriteBatch.Begin();
                if (canDropThrough == false)
                {
                    //spriteBatch.Draw(spriteSheet, pos + new Vector2(300, -80), Color.Red);
                }
                else
                {
                    spriteBatch.Draw(spriteSheet2, pos + new Vector2(-50, -80), Color.Red);
                }
                spriteBatch.End();
            }
            base.Draw(gameTime);
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        public Boolean isOnPlatform(Player p)
        {
            if ((p.Position.Y + p.curSpriteRect.spriteBox.Height <= this.pos.Y) && (p.Position.Y + p.curSpriteRect.spriteBox.Height + p.Velocity.Y + .4 > this.pos.Y))
            {
                int pX = (int)p.Position.X;
                int p2X = (int)p.Position.X + p.curSpriteRect.spriteBox.Width;
                if ((pX > pos.X) && (pX < (pos.X + length)))
                    return true;
                else if ((p2X > pos.X) && (p2X < (pos.X + length)))
                    return true;
            }

            return false;
        }

    }

    struct DisjointedAttack
    {
        public Vector2 pos;
        public Vector2 velocity;
        public static Texture2D sprite;
        public int player;
        public int attackType;

        public DisjointedAttack(Vector2 p, Vector2 v, int pl, int type)
        {
            pos = p;
            velocity = v;
            player = pl;
            attackType = type;
        }
    }
}